package com.huichenghe.xinlvsh01.Ble;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import com.huichenghe.xinlvsh01.MainActivity;
import com.huichenghe.xinlvsh01.R;
import com.huichenghe.xinlvsh01.Utils.DateUtils;
import com.huichenghe.xinlvsh01.Utils.FormatUtils;
import com.huichenghe.xinlvsh01.Utils.MyConfingInfo;
import com.huichenghe.xinlvsh01.Utils.MyToastUitls;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 处理app收到手环的数据，此类为单利
 * Created by lixiaoning on 15-11-9.
 */
public class BleNotifyParse
{
    public static final String TAG = "BleNotifyParse";
    private String mNotifyLock = "mNotifyLock";     // lock对象
    public static BleNotifyParse mBleNotifyParse;
    private BleNotifyParse()
    {

    };

    public static BleNotifyParse getInstance()
    {
        if(mBleNotifyParse == null)
        {
            mBleNotifyParse = new BleNotifyParse();
        }
        return mBleNotifyParse;
    }


    /**
     * 添加同步锁
     * @param mContext
     * @param notifyData
     */
    public void doParse(Context mContext, byte[] notifyData)
    {
        synchronized (mNotifyLock)
        {
            excuteParse(mContext, notifyData);
        }
    }

    private static final int BUFFER_MAX_LEN = 8 * 1024; // 最大长度
    private byte[] buffer = new byte[BUFFER_MAX_LEN];   // 母数组
    private byte[] bufferTmp = new byte[1024];          // 单条数据的数组
    private int bufferLength;       // 未处理的数据的长度
    private int bufferReadB;        // 已处理到的位置,处理过的数据不在bufferLength里边，

    /**
     * 此处理方式，为一个链式数组，新数据在数据尾部添加，读取数据从第一个开始读，下标超过最大值则轮换为0，再一次轮询
     * 从母数组中取出数据第一条数据
     * @param mContext
     * @param notifyData
     */
    private void excuteParse(Context mContext, byte[] notifyData)
    {
        Log.i(TAG, "excuteParse the data：："
                + FormatUtils.bytesToHexString(notifyData) + "++长度++" + notifyData.length);

        saveToFile(notifyData);                         // 保存到sd卡

        /**
         * 遍历当前数据，并添加到母数组
         */
        for (int i = 0; i < notifyData.length; i++)     // 遍历当前数据，
        {
            int pos = bufferReadB + bufferLength + i;   // pos为添加到母数组的起始位置
            pos %= BUFFER_MAX_LEN;                      // 下标超出母数组范围则循环到0，重新计数
            buffer[pos] = notifyData[i];                // 取出数据放入母数组
        }

        bufferLength += notifyData.length;              // bufferLength为未处理的数据的长度

        boolean isFindNotifyBegin = false;              // 标识当前数据是否为包头
        int notifyIndex = 0;                            // 标识一条数据开始的位置
        int msgLen = 0;                                 // 一条数据的长度

        Log.i(TAG, "buffer11Tmp : bufferReadB = " + bufferReadB + "; bufferLength = " + bufferLength);
        Log.i(TAG, "buffer11Tmp : buffer = " + FormatUtils.bytesToHexString(buffer));

        /**
         * 从母数组取数据并处理
         * 开始下标为读取到的位置，结束位置为数据的长度，即处理未处理的数据
         */

        for(int read = bufferReadB; read < bufferReadB + bufferLength; read ++)
        {

            int pos = read % BUFFER_MAX_LEN;
            if(buffer[pos] == 0x68 && !isFindNotifyBegin)   // 判断此条数据的包头
            {
                isFindNotifyBegin = true;
                notifyIndex = 0;                            // 标识此条数据开始位置
                msgLen = 6;                                 // 此变量为数据长度
            }
            if(isFindNotifyBegin)
            {
                bufferTmp[notifyIndex] = buffer[pos];
                notifyIndex ++;
            }

            /**
             * 解析数据长度
             */
            if(notifyIndex == 4)
            {
                msgLen = bytes2Char(bufferTmp, 2) + 4 + 2;  // 解析数据域长度
                if(msgLen > 1000)                           // 长度大于1000，数据错误
                {   // 重置标识
                    isFindNotifyBegin = false;
                    read = read - notifyIndex + 1;
                    notifyIndex = 0;
                }
            }

            if(isFindNotifyBegin && notifyIndex == msgLen)  // 数据结尾
            {
                if(buffer[pos] == 0x16)
                {   // 处理数据
                    excuteParse(mContext, bufferTmp, notifyIndex);
                    bufferLength -= (read - bufferReadB);   // 当前数据结束的位置，减去开始的位置，即当前数据长度，处理数据后总长去除此条数据
                    bufferReadB = pos + 1;                  // +1是下一条数据开始的下标
                    isFindNotifyBegin = false;
                    notifyIndex = 0;
                }
                else
                {   // 如果到了数据结尾却没有尾帧，则重置read值，重新遍历
                    isFindNotifyBegin = false;
                    read = read - notifyIndex + 1;
                }
            }


        }






    }


    /**
     * 重载方法处理一条完整的数据
     * @param mContext
     * @param bufferTmp
     * @param notifyIndex
     */
    private void excuteParse(final Context mContext, byte[] bufferTmp, int notifyIndex)
    {
        Log.i(TAG, "excuteParse当前解析的数据是：" + FormatUtils.bytesToHexString(bufferTmp));
//        68a000000816
        byte head = bufferTmp[0];       // 包头
        byte cmd = bufferTmp[1];        // 功能码
        int dataLen = bytes2Char(bufferTmp, 2);  // 数据长度
        Log.i("", "包头: " + (head & 0xff) + "\r\n" + "校验码：" + (cmd & 0xff)+ "\r\n" + "数据域长度：" + dataLen);
        if(dataLen > 1000 || bufferTmp.length < dataLen)    // 数据错误，直接结束
        {
            return;
        }
        byte[] theData = new byte[dataLen + 2];
        for (int i = 0; i < theData.length; i ++)
        {
            theData[i] = bufferTmp[i + 4];       // 从下标5开始取数据，到数据长度结束的位置，即取出的是当前数据的数据域
        }

        bufferTmp = theData;
        Log.i("", "解析后的数据域：" + FormatUtils.bytesToHexString(theData));

        if((cmd & 0xA0) == 0x80)
        {
            byte rece_cmd = (byte)(cmd & 0x0f);                 // 取十六进制码的第一个数
            if(rece_cmd == BleDataForBattery.mReceCmd)          // 接收的手环电量
            {
                BleDataForBattery.dealReceData(mContext, bufferTmp, dataLen);
            }
            else if(rece_cmd == BleDataForHardVersion.send_cmd) // 接收到的版本号
            {
                BleDataForHardVersion.dealReceData(mContext, bufferTmp, dataLen);
            }
            else if(rece_cmd == BleDataForSettingParams.getSettingCmd)
            {
//                new BleDataForSettingParams(mContext).dealBleResponse(MainActivity.this, bufferTmp, bufferTmp.length);
                ((Activity)mContext).runOnUiThread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        Toast.makeText(mContext, mContext.getString(R.string.step_pramas), Toast.LENGTH_SHORT).show();
                    }
                });

            }
            else if(rece_cmd == BleDataForCustomRemind.toDevice)    // 收到有数据的自定义提醒
            {
//                68 89 0700 00 00 04 01 0d34 2e 6c16
//                new BleDataForCustomRemind().dealTheValidData(mContext, bufferTmp);
                // 发送广播通知RemindActivity解析并显示数据
                Intent intent = new Intent();
                intent.setAction(MyConfingInfo.CUSTOM_REMIND_VALID);
                intent.putExtra(MyConfingInfo.CUSTOM_REMIND_VALID_DATA, bufferTmp);
                mContext.sendBroadcast(intent);


            }





        }
        else
        {
            byte notify_cmd = (byte)(cmd);
//            Log.i(TAG, notify_cmd + "----fromDevice" + BleDataForDayData.fromDevice);
            if(notify_cmd == (byte)(BleDataForDayData.fromDevice))        // 接收到手环的天数据,此为主页上的数据
            {
                Log.i(TAG, "a6数据---------：" + FormatUtils.bytesToHexString(bufferTmp));
                // 判断包类型，通过数据域第四个字节判断
                byte pagType = bufferTmp[3];
                if(pagType == (byte)0x00)
                {

                    new BleDataForDayData().dealDayData(mContext, bufferTmp);

                }
                else if(pagType == (byte)0x01)
                {
                    new BleDataForEachHourData(mContext).dealTheEachData(bufferTmp);
                }
                else if(pagType == (byte)0x02)
                {
                    new BleDataForSleepData(mContext).dealTheSleepData(bufferTmp);
                }
                else if(pagType == (byte)0x03)
                {
                    new BleDataForDayHeartReatData(mContext).dealTheHeartRateData(bufferTmp);
                }











            }
            else if(cmd == BleBaseDataForOutlineMovement.mNotify_cmd)   // 离线数据
            {
               new BleBaseDataForOutlineMovement().dealTheData(mContext, bufferTmp, dataLen);
                mContext.sendBroadcast(new Intent(MyConfingInfo.NOTIFY_MAINACTIVITY_TO_UPDATE_OUTLINE_DATA));
            }
        }




    }


    /**
     * 两个byte转化为int
     * @param data
     * @param offset
     * @return
     */
    int bytes2Char(byte[] data, int offset)
    {
        int va = data[offset] & 0xFF;               // 第三个数据，取最后八位
        int vb = (data[offset + 1] << 8) & 0xFFFF;  // 第四个数据，向左移动八位，取十六位
        return  va + vb;
    }

    /**
     * 将app收的到的数据保存到sd卡
     * @param notifyData
     */
    private void saveToFile(byte[] notifyData)
    {
        FileOutputStream out;
        String filePath = "/sdcard/recData";
        File fileP = new File(filePath);
        if(!fileP.exists())fileP.mkdir();
        File file = new File(filePath + "liveData.txt");
        if(!file.exists())
        {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try {
            out = new FileOutputStream(file, true);     // 创建输出流对象，true代表追加
            String str = "手环数据：" + DateUtils.getNowTimeToMill()
                    + FormatUtils.bytesToHexString(notifyData) + "/r/n";
            out.write(str.getBytes("UTF-8"));
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}
